#include <type.h>
#include <log.h>
#include <template.h>
#ifdef WIN32
#include <windows.h>
#endif
#include <cstream.h>
namespace mdk
{
#ifdef __cplusplus
    extern "C"
    {
#endif
        void (*_func_logWrite)(int level, const char *file, const char *func,
                               int line, const char *format, ...) = NULL;
        void logWrite(int level, const char *file, const char *func,
                      int line, const char *lpszFormat, ...)
        {
            std::string outstring;
            va_list argList;

            va_start(argList, lpszFormat);
            outstring = std::format(lpszFormat, argList);
            va_end(argList);

            static Logger logger;
            logger.Info(func, outstring.c_str());
#ifdef MDK_CFG_PRINT_LOG

#ifndef WIN32
            const char *endpos = NULL;
            endpos = strrchr(file, '\\');
            if (endpos == NULL)
                endpos = strrchr(file, '/');
            outstring = std::format("[%s:%d][%s]%s",
                                    (endpos != NULL ? endpos + 1 : file),
                                    line, func, outstring.c_str());
            std::cout << outstring << std::endl;
#else
            outstring = std::format("$$@@%s(%d)$$@@%d$$@@%s$$@@%5d(%5d)",
                                    func, line, level, outstring.c_str(),
                                    ::GetCurrentProcessId(),
                                    ::GetCurrentThreadId());
            //send message to dt.exe

            static HWND hwnd = ::FindWindowEx(NULL, NULL, NULL, ("DT "));
            if (!IsWindow(hwnd))
            {
                hwnd = ::FindWindowEx(NULL, NULL, NULL, ("DT "));
            }

            if (hwnd)
            {
                DWORD_PTR dwRet = 0;

                const char *msg = outstring.c_str();
                const int len = outstring.length();

                COPYDATASTRUCT cs = {
                    0,
                    outstring.length() + 1,
                    (LPVOID)outstring.c_str(),
                };
                SendMessageTimeout(hwnd, WM_COPYDATA, 0, (LPARAM)&cs,
                                   SMTO_BLOCK, 10 * 1000, (PDWORD_PTR)&dwRet);
            }
#endif
#endif // MDK_CFG_PRINT_LOG
        }
        /**
         * dump the hex format data to log
         *
         * @param name name for hex object, it will show on log header
         * @param width hex number for every line, such as: 16, 32
         * @param buf hex buffer
         * @param size buffer size
         */
        void hexdump(const char *name, int width,
                     const unsigned char *buf, int size)
        {
#define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ')
            uint16_t i, j;

            for (i = 0; i < size; i += width)
            {
                CByteBuffer buffer;
                /* package header */
                buffer.format("HEX %s: %04X-%04X: ", name, i, i + width - 1);
                /* dump hex */
                for (j = 0; j < width; j++)
                {
                    if (i + j < size)
                    {
                        buffer.format("%02X ", buf[i + j]);
                    }
                    else
                    {
                        buffer.Append((char *)"   ");
                    }
                }
                buffer.Append((char *)"    ");
                /* dump char for hex */
                for (j = 0; j < width; j++)
                {
                    if (i + j < size)
                    {
                        buffer.format("%c", __is_print(buf[i + j]) ? buf[i + j] : '.');
                    }
                }
                LOG_INFO(buffer.c_str());
            }
        }
#ifdef __cplusplus
    }
#endif
}